package com.example.d8_thread_pool;

import java.util.concurrent.*;

/**
 * 目标：线程池的创建 - 处理Runnable任务
 */
public class ThreadPoolTest1 {
    public static void main(String[] args) {
        // 1.通过ThreadPoolExecutor创建一个线程池对象
        /**
         * 参数一：corePoolSize：指定线程池的核心线程的数据
         * 参数二：maximumPoolSize：指定线程池的最大线程数据
         * 参数三：keepAliveTime：临时线程空闲存活的时间
         * 参数四：unit：指定临时线程的存活时间单位(秒,分,式,天)
         * 参数五：workQueue：任务队列,用于存放等待被执行的任务
         * 参数六：threadFactory：用于创建线程的工厂
         * 参数七：handler：拒绝策略,当任务太多来不及处理,就会把任务丢给拒绝策略
         */
        ExecutorService pool = new ThreadPoolExecutor(3, // 核心线程数有3个
                5, // 最大线程数有5个   临时线程数 = 最大线程数 - 核心线程数 = 5 - 3 = 2
                8, // 临时线程存活的时间8秒 意思是临时线程8秒没有任务执行,就会被销毁掉
                TimeUnit.SECONDS, // 时间单位（秒）
                new ArrayBlockingQueue<>(4), // 任务阻塞队列,没有来得及执行的任务在,任务队列中等待
                Executors.defaultThreadFactory(), // 用于创建线程的工厂对象
                new ThreadPoolExecutor.CallerRunsPolicy()); // 任务的拒绝策略

        // 线程池处理Runnable任务
        /*
        void execute(Runnable command) 执行Runnable任务
        Future<?> submit(Runnable task) 执行Callable任务,返回未来任务对象,用于获取线程的返回结果
        void shutdown() 等待全部任务执行完毕在关闭线程池
        List<Runnable> shutdownNow() 立即关闭线程池,停止正在执行的任务,并返回队列中未执行的任务
         */

        Runnable target = new MyRunnable();
        pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的
        pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的
        pool.execute(target); // 线程池会自动创建一个新线程,自动处理这个任务,自动执行的
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        // 到了创建临时线程的时机：核心线程都在忙,任务队列也满了,此时才会创建临时线程
        pool.execute(target);
        pool.execute(target);
        // 到了新拒绝的时机：临时线程都在忙,任务队列也满了,此时才会拒绝新任务
        // 任务的拒绝策略
        /*
        1.AbortPolicy: 默认的拒绝策略,丢弃任务并抛出RejectedExecutionException异常
        2.CallerRunsPolicy: 由主线程直接去处理这个任务
        3.DiscardPolicy: 什么也不做,直接丢弃任务,不推荐的做法
        4.DiscardOldestPolicy: 丢弃队列中最老的任务,把当前任务加入队列中
         */
        pool.execute(target);

        // pool.shutdown(); // 等待全部任务执行完毕在关闭线程池
        // pool.shutdownNow(); // 立即关闭线程池,停止正在执行的任务,并返回队列中未执行的任务

        // 线程池的注意事项
        // 1.临时线程什么时候创建?
        // 新任务提交的时候发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程

        // 2.什么时候会开始拒绝新任务?
        // 核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务
    }
}
